package com.wondersgroup.restbase.dto;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.wondersgroup.restbase.util.AccessorUtils;

/**
 * 包含dto和业务实体之间的映射信息
 * @author wondersgroup
 *
 */
public class DtoFieldMapInfo {

	/**dto的字段名*/
	private String thisField;
	/**业务实体的字段名*/
	private String modelField;
	/**是否从请求获取*/
	private boolean input;
	/**是否从写入响应*/
	private boolean output;

	public String getThisField() {
		return thisField;
	}

	public void setThisField(String thisField) {
		this.thisField = thisField;
	}

	public String getModelField() {
		return modelField;
	}

	public void setModelField(String modelField) {
		this.modelField = modelField;
	}

	@Override
	public String toString() {
		return thisField + " -> " + modelField + " , input: " + input + " , output: " + output;
	}

	public static <DTO> List<DtoFieldMapInfo> build(Class<DTO> dtoClass) {
		DtoFieldsMapping fieldsMapping = dtoClass.getAnnotation(DtoFieldsMapping.class);
		List<DtoFieldMapInfo> mapList = new ArrayList<DtoFieldMapInfo>();
		if (fieldsMapping != null) {
			for (DtoFieldMapping fieldMapping : fieldsMapping.value()) {
				DtoFieldMapInfo mapInfo = new DtoFieldMapInfo();
				mapInfo.setModelField(fieldMapping.modelField());
				mapInfo.setThisField(fieldMapping.thisField());
				mapInfo.setInput(fieldMapping.input());
				mapInfo.setOutput(fieldMapping.output());
				mapList.add(mapInfo);
			}
		}
		for (Field field : dtoClass.getDeclaredFields()) {
			DtoFieldMapping fieldMapping = field.getAnnotation(DtoFieldMapping.class);
			if (fieldMapping != null) {
				DtoFieldMapInfo mapInfo = new DtoFieldMapInfo();
				if (fieldMapping.modelField().equals("")) {
					mapInfo.setModelField(field.getName());
				} else {
					mapInfo.setModelField(fieldMapping.modelField());
				}
				if (fieldMapping.thisField().equals("")) {
					mapInfo.setThisField(field.getName());
				} else {
					mapInfo.setThisField(fieldMapping.thisField());
				}
				mapInfo.setInput(fieldMapping.input());
				mapInfo.setOutput(fieldMapping.output());
				mapList.add(mapInfo);
			}
		}
		return mapList;
	}

	@SuppressWarnings("rawtypes")
	public <DTO, MODEL> void setModelField(DTO dto, MODEL model) throws Exception {

		if (!input)
			return;

		Method getter = AccessorUtils.findGetter(dto, getThisField());
		if (getter.invoke(dto) == null)
			return;

		if (getModelField().indexOf(".") < 0) {

			Method setter = AccessorUtils.findSetter(model, getModelField());
			// modify by wym 增加对日期类型的处理
			Class firstParamType = setter.getParameterTypes()[0];
			if (firstParamType == java.util.Date.class) {
				Date date = null;
				String arg = (String) getter.invoke(dto);
				if (arg != null && !arg.equals("")) {
					String formatStr = arg.split(" ").length > 1 ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd";
					SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
					date = sdf.parse(arg);
				}
				setter.invoke(model, date);
			} else if (firstParamType == java.lang.Integer.class) {
				setter.invoke(model, Integer
						.parseInt((getter.invoke(dto).toString()).equals("") ? "0" : getter.invoke(dto).toString()));
			} else {
				setter.invoke(model, getter.invoke(dto));
			}

		} else {
			String[] fields = getModelField().split("\\.");

			Object obj = model;
			for (int i = 0; i < fields.length - 1; i++) {
				Method m = AccessorUtils.findGetter(obj, fields[i]);
				Object ret = m.invoke(obj);
				if (ret == null) {
					ret = m.getReturnType().newInstance();
					AccessorUtils.findSetter(obj, fields[i]).invoke(obj, ret);
				}
				obj = ret;
			}

			AccessorUtils.findSetter(obj, fields[fields.length - 1]).invoke(obj, getter.invoke(dto));
		}
	}

	public boolean isInput() {
		return input;
	}

	public void setInput(boolean input) {
		this.input = input;
	}

	public boolean isOutput() {
		return output;
	}

	public void setOutput(boolean output) {
		this.output = output;
	}
}
